Þ ¥bonds€¬cell_resultsÞ Ù$005b40d9-bd89-4491-9807-d33a6c674b75Š¦queuedÂ¤logs�§runningÂ¦output†¤body‚£msgÙ5MethodError: objects of type Nothing are not callableªstacktrace‘Œªcall_short¯top-level scope§inlinedÃ£urlÀ¤pathÙp/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#005b40d9-bd89-4491-9807-d33a6c674b75®source_packageÀ¤call¯top-level scopeªlinfo_type§Nothing¤line¤fileÙ:reactive python.jl#==#005b40d9-bd89-4491-9807-d33a6c674b75¤func»##function_wrapped_cell#308­parent_moduleÀ¦from_cÂ¤mimeÙ'application/vnd.pluto.stacktrace+object¬rootassigneeÀ²last_run_timestampËAÚþgÙC°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$005b40d9-bd89-4491-9807-d33a6c674b75¹depends_on_disabled_cellsÂ§runtimeÀµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÃÙ$12814f02-7e90-401a-9573-5c6b2f8067aeŠ¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþbD<K°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$12814f02-7e90-401a-9573-5c6b2f8067ae¹depends_on_disabled_cellsÂ§runtimeÍcµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$6449e96f-19ce-4100-8b35-56113bc24b7dŠ¦queuedÂ¤logs�§runningÂ¦output†¤bodyÚExpr
  head: Symbol macrocall
  args: Array{Any}((3,))
    1: Symbol @py_str
    2: LineNumberNode
      line: Int64 1
      file: Symbol /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#6449e96f-19ce-4100-8b35-56113bc24b7d
    3: String "[1+1]"
¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþgë¬G°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$6449e96f-19ce-4100-8b35-56113bc24b7d¹depends_on_disabled_cellsÂ§runtimeÎ 7‰Éµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$5f5ab869-c551-42d3-9325-86ecdc424c9bŠ¦queuedÂ¤logs�§runningÂ¦output†¤bodyÙ"@pyr_old_str (macro with 1 method)¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþhÓ™³°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$5f5ab869-c551-42d3-9325-86ecdc424c9b¹depends_on_disabled_cellsÂ§runtimeÎ vµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$56a3a022-6ed3-47d8-8d62-ce4ead5ca026Š¦queuedÂ¤logs�§runningÂ¦output†¤body‚£msgÙ#UndefVarError: @pyr_str not definedªstacktrace“Œªcall_short¯top-level scope§inlinedÂ£urlÀ¤path ®source_packageÀ¤call¯top-level scopeªlinfo_type§Nothing¤line ¤file ¤func¯top-level scope­parent_moduleÀ¦from_cÂŒªcall_short¯#macroexpand#51§inlinedÃ£urlÀ¤path©./expr.jl®source_packageÀ¤call¯#macroexpand#51ªlinfo_type§Nothing¤lineu¤file§expr.jl¤func¯#macroexpand#51­parent_moduleÀ¦from_cÂŒªcall_short¯top-level scope§inlinedÃ£urlÀ¤pathÙp/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#56a3a022-6ed3-47d8-8d62-ce4ead5ca026®source_packageÀ¤call¯top-level scopeªlinfo_type§Nothing¤line¤fileÙ:reactive python.jl#==#56a3a022-6ed3-47d8-8d62-ce4ead5ca026¤func»##function_wrapped_cell#322­parent_moduleÀ¦from_cÂ¤mimeÙ'application/vnd.pluto.stacktrace+object¬rootassigneeÀ²last_run_timestampËAÚþhýð°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$56a3a022-6ed3-47d8-8d62-ce4ead5ca026¹depends_on_disabled_cellsÂ§runtimeÀµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÃÙ$e07e4a47-a3cc-4ca4-a946-29e7df33ec6dŠ¦queuedÂ¤logs�§runningÂ¦output†¤bodyÚ­<div class="markdown"><h1>Reactive Python</h1>
<p>The <code>pyr&quot;</code> macro is just like the <code>py&quot;</code> macro from <code>PyCall.jl</code>, except it is reactive&#33; This means:</p>
<ul>
<li><p>If you define a Python variable, then other cells that use that python variable are also evaluated.</p>
</li>
<li><p>The scope of Python variables is cleaned up automatically.</p>
</li>
<li><p>Multiple definitions are not allowed.</p>
</li>
</ul>
<p>This is using the Python port of Pluto.ExpressionExplorer by MikoÅ‚aj Bochenski: <a href="https://github.com/lightning-notebook/engine">https://github.com/lightning-notebook/engine</a> and some Julia macro magic.</p>
</div>¤mime©text/html¬rootassigneeÀ²last_run_timestampËAÚþg\;d°persist_js_stateÃ·has_pluto_hook_featuresÂ§cell_idÙ$e07e4a47-a3cc-4ca4-a946-29e7df33ec6d¹depends_on_disabled_cellsÂ§runtimeÎT’µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$56fcc0c2-0ce0-445b-b602-6525bab173b3Š¦queuedÂ¤logs�§runningÂ¦output†¤bodyƒ¨elements’’’¨0.747367ªtext/plain’’§nothingªtext/plain¤type¥Tuple¨objectid°8e3a45e69275c07b¤mimeÙ!application/vnd.pluto.tree+object¬rootassigneeÀ²last_run_timestampËAÚþh§i°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$56fcc0c2-0ce0-445b-b602-6525bab173b3¹depends_on_disabled_cellsÂ§runtimeÎ aî?µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$21199966-adc3-498e-87ae-62333810efb5Š¦queuedÂ¤logs�§runningÂ¦output†¤bodyÚàquote
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:8 =#
    begin
        #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:12 =#
        let s = var"py#var_b"
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:13 =#
            begin
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
                var"#471#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
                begin
                    var"#471#m"["__julia_localvar_25_1"] = Main.workspace#4.PyObject(s)
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
                var"#472#ret" = (PyAny)(Main.workspace#4.pyeval_(Base.string("b = __julia_localvar_25_1\n"), var"#471#m", var"#471#m", 257, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
                nothing
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
                var"#472#ret"
            end
        end
    end
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:19 =#
    var"#470#output" = begin
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
            var"#473#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
            begin
            end
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
            var"#474#ret" = (PyAny)(Main.workspace#4.pyeval_((Main.workspace#5.Base).string("x = 123\ny = b\n"), var"#473#m", var"#473#m", 257, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
            nothing
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
            var"#474#ret"
        end
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:23 =#
    begin
        #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:27 =#
        var"py#var_x" = begin
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
                var"#475#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
                var"#476#ret" = (PyAny)(Main.workspace#4.pyeval_(Base.string("x"), var"#475#m", var"#475#m", 258, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
                var"#476#ret"
            end
    end
    begin
        #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:27 =#
        var"py#var_y" = begin
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
                var"#477#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
                var"#478#ret" = (PyAny)(Main.workspace#4.pyeval_(Base.string("y"), var"#477#m", var"#477#m", 258, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
                var"#478#ret"
            end
    end
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:31 =#
    var"#470#output"
end¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþhÅ5˜°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$21199966-adc3-498e-87ae-62333810efb5¹depends_on_disabled_cellsÂ§runtimeÎ –µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$73c3f448-be7d-49b7-9e39-18c3a08feb01Š¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþhŸ„¾°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$73c3f448-be7d-49b7-9e39-18c3a08feb01¹depends_on_disabled_cellsÂ§runtimeÎ	²¡‚µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$fb3fb09d-1ba7-431e-aba2-f832d259075aŠ¦queuedÂ¤logs�§runningÂ¦output†¤body§1123124¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþhÈè«°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$fb3fb09d-1ba7-431e-aba2-f832d259075a¹depends_on_disabled_cellsÂ§runtimeÎ Zâµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7Š¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþfŒ°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7¹depends_on_disabled_cellsÂ§runtimeÎ †éµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$600344b6-ff43-431b-b858-2bf30e93d938Š¦queuedÂ¤logs�§runningÂ¦output†¤bodyÙý<div class="markdown"><p>Following code is from <a href="https://github.com/lightning-notebook/engine/blob/master/tests/test_variable_access.py">https://github.com/lightning-notebook/engine/blob/master/tests/test<em>variable</em>access.py</a></p>
</div>¤mime©text/html¬rootassigneeÀ²last_run_timestampËAÚþg^Mb°persist_js_stateÃ·has_pluto_hook_featuresÂ§cell_idÙ$600344b6-ff43-431b-b858-2bf30e93d938¹depends_on_disabled_cellsÂ§runtimeÎ¼9µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$688c93e7-b50f-4bb7-ab23-5686fd8ffb18Š¦queuedÂ¤logs�§runningÂ¦output†¤body¡2¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþh@ì�°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$688c93e7-b50f-4bb7-ab23-5686fd8ffb18¹depends_on_disabled_cellsÂ§runtimeÎúŽ}µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$a1ada27d-8a1a-453a-ace7-ae07b68ad42aŠ¦queuedÂ¤logs�§runningÂ¦output†¤body£123¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþbDŠ°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$a1ada27d-8a1a-453a-ace7-ae07b68ad42a¹depends_on_disabled_cellsÂ§runtimeÍµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$b9903477-5070-43eb-82a9-8b750f79c8faŠ¦queuedÂ¤logs�§runningÂ¦output†¤bodyÙ$@custom_py_str (macro with 1 method)¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþh!´°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$b9903477-5070-43eb-82a9-8b750f79c8fa¹depends_on_disabled_cellsÂ§runtimeÎ Gmzµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$71ca495d-39ad-4d52-94a5-d4248679ce1eŠ¦queuedÂ¤logs�§runningÂ¦output†¤body…¦prefix¯PyCall.PyObject¨elements’’’´PyObject frozenset()ªtext/plain’’¹PyObject frozenset({'x'})ªtext/plain¤type¥Array¬prefix_short ¨objectid¯26cd57b35a0b609¤mimeÙ!application/vnd.pluto.tree+object¬rootassignee¢rw²last_run_timestampËAÚþhq÷¶°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$71ca495d-39ad-4d52-94a5-d4248679ce1e¹depends_on_disabled_cellsÂ§runtimeÎ40µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16Š¦queuedÂ¤logs�§runningÂ¦output†¤body¾@pyr_str (macro with 1 method)¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþh�0#°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16¹depends_on_disabled_cellsÂ§runtimeÎ %z+µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$f4d3b313-1c8c-4de1-b5bd-592cb1112068Š¦queuedÂ¤logs�§runningÂ¦output†¤body…¦prefix¥Int64¨elements’’’¡2ªtext/plain’’¡4ªtext/plain¤type¥Array¬prefix_short ¨objectid°d34fe57a218fd7d9¤mimeÙ!application/vnd.pluto.tree+object¬rootassigneeÀ²last_run_timestampËAÚþh¯Ð¢°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$f4d3b313-1c8c-4de1-b5bd-592cb1112068¹depends_on_disabled_cellsÂ§runtimeÎ:¿ùµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$5dc1c311-1004-4056-b0a9-06622546486eŠ¦queuedÂ¤logs�§runningÂ¦output†¤body¦123123¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþhµñÌ°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$5dc1c311-1004-4056-b0a9-06622546486e¹depends_on_disabled_cellsÂ§runtimeÎ ³Aµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7eŠ¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþbDÑ[°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7e¹depends_on_disabled_cellsÂ§runtimeÍ!žµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bŠ¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþf‘0s°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b¹depends_on_disabled_cellsÂ§runtimeÎY¯àµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$d9bc5dc1-67b6-47c6-9592-3b474ec451a0Š¦queuedÂ¤logs�§runningÂ¦output†¤bodyÚExpr
  head: Symbol macrocall
  args: Array{Any}((3,))
    1: Symbol @py_str
    2: LineNumberNode
      line: Int64 1
      file: Symbol /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#d9bc5dc1-67b6-47c6-9592-3b474ec451a0
    3: String "[1+1]\n"
¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþgëÕ·°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$d9bc5dc1-67b6-47c6-9592-3b474ec451a0¹depends_on_disabled_cellsÂ§runtimeÎ Ôˆµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$e8873c23-139d-41bc-be35-ebd636e48aeeŠ¦queuedÂ¤logs�§runningÂ¦output†¤body²0.9092974268256817¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþg†!Ù°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$e8873c23-139d-41bc-be35-ebd636e48aee¹depends_on_disabled_cellsÂ§runtimeÎmcµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$d74aed51-9542-47aa-8c3d-fb634c1a0212Š¦queuedÂ¤logs�§runningÂ¦output†¤bodyÙ2PyObject <function reads_writes at 0x7fd600fd87c0>¤mimeªtext/plain¬rootassignee¯py_reads_writes²last_run_timestampËAÚþhPÆ¤°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$d74aed51-9542-47aa-8c3d-fb634c1a0212¹depends_on_disabled_cellsÂ§runtimeÎÅoôµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$ab92a31d-1ef4-427f-b1c7-fa2790278a14Š¦queuedÂ¤logs�§runningÂ¦output†¤body…¦prefix£Any¨elements‘’’£"x"ªtext/plain¤type¥Array¬prefix_short ¨objectid¯366f9610a9dc99e¤mimeÙ!application/vnd.pluto.tree+object¬rootassigneeÀ²last_run_timestampËAÚþh‚öÇ°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$ab92a31d-1ef4-427f-b1c7-fa2790278a14¹depends_on_disabled_cellsÂ§runtimeÎ ´?pµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$b59d932b-6425-47c2-a67d-208113bc8b7bŠ¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþgg¾s°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$b59d932b-6425-47c2-a67d-208113bc8b7b¹depends_on_disabled_cellsÂ§runtimeÎ¬â£µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bŠ¦queuedÂ¤logs�§runningÂ¦output†¤body¡3¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþh>b°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b¹depends_on_disabled_cellsÂ§runtimeÎ¯˜qµpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Š¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþh&t°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¹depends_on_disabled_cellsÂ§runtimeÎ 
¥µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$dd20f208-0e39-4255-b35a-a8189986a165Š¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþh²­y°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$dd20f208-0e39-4255-b35a-a8189986a165¹depends_on_disabled_cellsÂ§runtimeÎ 
À$µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$f93f0eef-bb0c-45ee-a080-e8eeb6611176Š¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþhœ0±°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$f93f0eef-bb0c-45ee-a080-e8eeb6611176¹depends_on_disabled_cellsÂ§runtimeÎ -½µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂÙ$216e88b3-82cb-4d74-aae4-c21791980ac2Š¦queuedÂ¤logs�§runningÂ¦output†¤body ¤mimeªtext/plain¬rootassigneeÀ²last_run_timestampËAÚþhÈx°persist_js_stateÂ·has_pluto_hook_featuresÂ§cell_idÙ$216e88b3-82cb-4d74-aae4-c21791980ac2¹depends_on_disabled_cellsÂ§runtimeÎ 	¥2µpublished_object_keys�¸depends_on_skipped_cellsÂ§erroredÂ±cell_dependenciesÞ Ù$005b40d9-bd89-4491-9807-d33a6c674b75„´precedence_heuristic	§cell_idÙ$005b40d9-bd89-4491-9807-d33a6c674b75´downstream_cells_map‚¦#414#m�¨#415#ret�²upstream_cells_map‡«Base.string�¤Base�²PyCall.pynamespace�§@py_str�º#___this_pluto_module_name�¦PyCall‘Ù$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b®PyCall.pyeval_�Ù$12814f02-7e90-401a-9573-5c6b2f8067ae„´precedence_heuristic	§cell_idÙ$12814f02-7e90-401a-9573-5c6b2f8067ae´downstream_cells_map€²upstream_cells_map€Ù$6449e96f-19ce-4100-8b35-56113bc24b7d„´precedence_heuristic	§cell_idÙ$6449e96f-19ce-4100-8b35-56113bc24b7d´downstream_cells_map€²upstream_cells_map�¤Dump�Ù$5f5ab869-c551-42d3-9325-86ecdc424c9b„´precedence_heuristic	§cell_idÙ$5f5ab869-c551-42d3-9325-86ecdc424c9b´downstream_cells_map�¬@pyr_old_str�²upstream_cells_map„¯py_reads_writes‘Ù$d74aed51-9542-47aa-8c3d-fb634c1a0212£esc�®@custom_py_str‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa¦Symbol�Ù$56a3a022-6ed3-47d8-8d62-ce4ead5ca026„´precedence_heuristic	§cell_idÙ$56a3a022-6ed3-47d8-8d62-ce4ead5ca026´downstream_cells_map€²upstream_cells_map†¤Meta�¤Base�°Meta.macroexpand�«@__MODULE__�º#___this_pluto_module_name�µBase.remove_linenums!�Ù$e07e4a47-a3cc-4ca4-a946-29e7df33ec6d„´precedence_heuristic	§cell_idÙ$e07e4a47-a3cc-4ca4-a946-29e7df33ec6d´downstream_cells_map€²upstream_cells_map‚§@md_str�¨getindex�Ù$56fcc0c2-0ce0-445b-b602-6525bab173b3„´precedence_heuristic	§cell_idÙ$56fcc0c2-0ce0-445b-b602-6525bab173b3´downstream_cells_map€²upstream_cells_map‚©#py_var_x�¤rand�Ù$21199966-adc3-498e-87ae-62333810efb5„´precedence_heuristic	§cell_idÙ$21199966-adc3-498e-87ae-62333810efb5´downstream_cells_map€²upstream_cells_map…¤Base�¬@macroexpand�°Base.macroexpand�º#___this_pluto_module_name�¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16Ù$73c3f448-be7d-49b7-9e39-18c3a08feb01„´precedence_heuristic	§cell_idÙ$73c3f448-be7d-49b7-9e39-18c3a08feb01´downstream_cells_map†¨#431#ret�¨py#var_y‘Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068¨#433#ret�¦#432#m�«#427#output�¦#430#m�²upstream_cells_mapˆ«Base.string�¤Main�¤Base�§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨PyObject�«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16¨py#var_x‘Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$fb3fb09d-1ba7-431e-aba2-f832d259075a„´precedence_heuristic	§cell_idÙ$fb3fb09d-1ba7-431e-aba2-f832d259075a´downstream_cells_mapƒ¦#452#m�¨#453#ret�«#449#output�²upstream_cells_mapˆ«Base.string�¤Main�¤Base�¨py#var_f‘Ù$216e88b3-82cb-4d74-aae4-c21791980ac2¨PyObject�«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Ù$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7„´precedence_heuristic§cell_idÙ$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7´downstream_cells_map�£Pkg�²upstream_cells_map€Ù$600344b6-ff43-431b-b858-2bf30e93d938„´precedence_heuristic	§cell_idÙ$600344b6-ff43-431b-b858-2bf30e93d938´downstream_cells_map€²upstream_cells_map‚§@md_str�¨getindex�Ù$688c93e7-b50f-4bb7-ab23-5686fd8ffb18„´precedence_heuristic	§cell_idÙ$688c93e7-b50f-4bb7-ab23-5686fd8ffb18´downstream_cells_map‚¨#422#ret�¦#421#m�²upstream_cells_map†«Base.string�¤Main�¤Base�®@custom_py_str‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Ù$a1ada27d-8a1a-453a-ace7-ae07b68ad42a„´precedence_heuristic	§cell_idÙ$a1ada27d-8a1a-453a-ace7-ae07b68ad42a´downstream_cells_map€²upstream_cells_map€Ù$b9903477-5070-43eb-82a9-8b750f79c8fa„´precedence_heuristic	§cell_idÙ$b9903477-5070-43eb-82a9-8b750f79c8fa´downstream_cells_map�®@custom_py_str”Ù$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16Ù$5f5ab869-c551-42d3-9325-86ecdc424c9bÙ$688c93e7-b50f-4bb7-ab23-5686fd8ffb18²upstream_cells_mapÞ ¤Core�ªfirstindex�©lastindex�¤keys�£esc�¦filter�¨PyObject�¦String�¤Expr�§nothing�¦length�­Py_file_input‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¢==�¢in�²interpolate_pycode‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5ªmake_fname‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5©@__FILE__�¡:�§collect�§prevind�§Integer�£isa�¥push!�¥sort!�­Py_eval_input‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¥PyAny�ªCore._expr�Ù$71ca495d-39ad-4d52-94a5-d4248679ce1e„´precedence_heuristic	§cell_idÙ$71ca495d-39ad-4d52-94a5-d4248679ce1e´downstream_cells_map�¢rw‘Ù$ab92a31d-1ef4-427f-b1c7-fa2790278a14²upstream_cells_map�¯py_reads_writes‘Ù$d74aed51-9542-47aa-8c3d-fb634c1a0212Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16„´precedence_heuristic	§cell_idÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16´downstream_cells_map�¨@pyr_str˜Ù$73c3f448-be7d-49b7-9e39-18c3a08feb01Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068Ù$dd20f208-0e39-4255-b35a-a8189986a165Ù$5dc1c311-1004-4056-b0a9-06622546486eÙ$21199966-adc3-498e-87ae-62333810efb5Ù$fb3fb09d-1ba7-431e-aba2-f832d259075aÙ$216e88b3-82cb-4d74-aae4-c21791980ac2²upstream_cells_map„¯py_reads_writes‘Ù$d74aed51-9542-47aa-8c3d-fb634c1a0212£esc�®@custom_py_str‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa¦Symbol�Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068„´precedence_heuristic	§cell_idÙ$f4d3b313-1c8c-4de1-b5bd-592cb1112068´downstream_cells_mapƒ¦#459#m�¨#460#ret�«#454#output�²upstream_cells_map‰«Base.string�¤Main�¤Base�§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨py#var_y‘Ù$73c3f448-be7d-49b7-9e39-18c3a08feb01¨PyObject�«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16¨py#var_x‘Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$5dc1c311-1004-4056-b0a9-06622546486e„´precedence_heuristic	§cell_idÙ$5dc1c311-1004-4056-b0a9-06622546486e´downstream_cells_mapƒ¨#467#ret�¦#466#m�«#461#output�²upstream_cells_map‰«Base.string�¤Main�¤Base�§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨PyObject�«py#var_cool‘Ù$dd20f208-0e39-4255-b35a-a8189986a165«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16¨py#var_x‘Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7e„´precedence_heuristic	§cell_idÙ$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7e´downstream_cells_map€²upstream_cells_map€Ù$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b„´precedence_heuristic§cell_idÙ$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b´downstream_cells_map�¦PyCall“Ù$e8873c23-139d-41bc-be35-ebd636e48aeeÙ$005b40d9-bd89-4491-9807-d33a6c674b75Ù$d74aed51-9542-47aa-8c3d-fb634c1a0212²upstream_cells_map€Ù$d9bc5dc1-67b6-47c6-9592-3b474ec451a0„´precedence_heuristic	§cell_idÙ$d9bc5dc1-67b6-47c6-9592-3b474ec451a0´downstream_cells_map€²upstream_cells_map�¤Dump�Ù$e8873c23-139d-41bc-be35-ebd636e48aee„´precedence_heuristic	§cell_idÙ$e8873c23-139d-41bc-be35-ebd636e48aee´downstream_cells_map„¨#419#ret�¨#417#ret�¦#418#m�¦#416#m�²upstream_cells_map‡«Base.string�¤Base�²PyCall.pynamespace�§@py_str�º#___this_pluto_module_name�¦PyCall‘Ù$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b®PyCall.pyeval_�Ù$d74aed51-9542-47aa-8c3d-fb634c1a0212„´precedence_heuristic	§cell_idÙ$d74aed51-9542-47aa-8c3d-fb634c1a0212´downstream_cells_map…¨#413#ret�¦#412#m�¯py_reads_writes“Ù$71ca495d-39ad-4d52-94a5-d4248679ce1eÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16Ù$5f5ab869-c551-42d3-9325-86ecdc424c9b¦#410#m�¨#411#ret�²upstream_cells_map‡«Base.string�¤Base�²PyCall.pynamespace�§@py_str�º#___this_pluto_module_name�¦PyCall‘Ù$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b®PyCall.pyeval_�Ù$ab92a31d-1ef4-427f-b1c7-fa2790278a14„´precedence_heuristic	§cell_idÙ$ab92a31d-1ef4-427f-b1c7-fa2790278a14´downstream_cells_map€²upstream_cells_mapƒ¢rw‘Ù$71ca495d-39ad-4d52-94a5-d4248679ce1e§collect�¢|>�Ù$b59d932b-6425-47c2-a67d-208113bc8b7b„´precedence_heuristic§cell_idÙ$b59d932b-6425-47c2-a67d-208113bc8b7b´downstream_cells_map�§PlutoUI�²upstream_cells_map€Ù$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b„´precedence_heuristic	§cell_idÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b´downstream_cells_map„¨#426#ret�¨#424#ret�¦#425#m�¦#423#m�²upstream_cells_map†«Base.string�¤Main�¤Base�®@custom_py_str‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5„´precedence_heuristic	§cell_idÙ$d3fe9870-ac9d-4871-b8cc-1361a446b0a5´downstream_cells_map†ªmake_fname‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa­Py_file_input‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa­Py_eval_input‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa«pynamespace™Ù$73c3f448-be7d-49b7-9e39-18c3a08feb01Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068Ù$dd20f208-0e39-4255-b35a-a8189986a165Ù$5dc1c311-1004-4056-b0a9-06622546486eÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bÙ$fb3fb09d-1ba7-431e-aba2-f832d259075aÙ$216e88b3-82cb-4d74-aae4-c21791980ac2Ù$688c93e7-b50f-4bb7-ab23-5686fd8ffb18²interpolate_pycode‘Ù$b9903477-5070-43eb-82a9-8b750f79c8fa§pyeval_™Ù$73c3f448-be7d-49b7-9e39-18c3a08feb01Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068Ù$dd20f208-0e39-4255-b35a-a8189986a165Ù$5dc1c311-1004-4056-b0a9-06622546486eÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bÙ$fb3fb09d-1ba7-431e-aba2-f832d259075aÙ$216e88b3-82cb-4d74-aae4-c21791980ac2Ù$688c93e7-b50f-4bb7-ab23-5686fd8ffb18²upstream_cells_map€Ù$dd20f208-0e39-4255-b35a-a8189986a165„´precedence_heuristic	§cell_idÙ$dd20f208-0e39-4255-b35a-a8189986a165´downstream_cells_map†¨#438#ret�«#434#output�¦#435#m�¨#436#ret�¦#437#m�«py#var_cool‘Ù$5dc1c311-1004-4056-b0a9-06622546486e²upstream_cells_map†«Base.string�¤Main�¤Base�«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176„´precedence_heuristic	§cell_idÙ$f93f0eef-bb0c-45ee-a080-e8eeb6611176´downstream_cells_map†¦#447#m�«#444#output�¨#448#ret�¦#445#m�¨#446#ret�¨py#var_x“Ù$73c3f448-be7d-49b7-9e39-18c3a08feb01Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068Ù$5dc1c311-1004-4056-b0a9-06622546486e²upstream_cells_map†«Base.string�¤Main�¤Base�«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Ù$216e88b3-82cb-4d74-aae4-c21791980ac2„´precedence_heuristic	§cell_idÙ$216e88b3-82cb-4d74-aae4-c21791980ac2´downstream_cells_map†¦#440#m�¨py#var_f‘Ù$fb3fb09d-1ba7-431e-aba2-f832d259075a¨#441#ret�¨#443#ret�¦#442#m�«#439#output�²upstream_cells_map†«Base.string�¤Main�¤Base�«pynamespace‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¨@pyr_str‘Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16§pyeval_‘Ù$d3fe9870-ac9d-4871-b8cc-1361a446b0a5´cell_execution_orderÜ Ù$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7Ù$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bÙ$b59d932b-6425-47c2-a67d-208113bc8b7bÙ$e07e4a47-a3cc-4ca4-a946-29e7df33ec6dÙ$12814f02-7e90-401a-9573-5c6b2f8067aeÙ$e8873c23-139d-41bc-be35-ebd636e48aeeÙ$005b40d9-bd89-4491-9807-d33a6c674b75Ù$6449e96f-19ce-4100-8b35-56113bc24b7dÙ$d9bc5dc1-67b6-47c6-9592-3b474ec451a0Ù$56fcc0c2-0ce0-445b-b602-6525bab173b3Ù$a1ada27d-8a1a-453a-ace7-ae07b68ad42aÙ$56a3a022-6ed3-47d8-8d62-ce4ead5ca026Ù$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7eÙ$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Ù$b9903477-5070-43eb-82a9-8b750f79c8faÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bÙ$688c93e7-b50f-4bb7-ab23-5686fd8ffb18Ù$600344b6-ff43-431b-b858-2bf30e93d938Ù$d74aed51-9542-47aa-8c3d-fb634c1a0212Ù$71ca495d-39ad-4d52-94a5-d4248679ce1eÙ$ab92a31d-1ef4-427f-b1c7-fa2790278a14Ù$5c432b4e-60e0-4288-8d5a-42e364ce8d16Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$73c3f448-be7d-49b7-9e39-18c3a08feb01Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068Ù$dd20f208-0e39-4255-b35a-a8189986a165Ù$5dc1c311-1004-4056-b0a9-06622546486eÙ$21199966-adc3-498e-87ae-62333810efb5Ù$216e88b3-82cb-4d74-aae4-c21791980ac2Ù$fb3fb09d-1ba7-431e-aba2-f832d259075aÙ$5f5ab869-c551-42d3-9325-86ecdc424c9b´last_hot_reload_timeË        ©shortpath²reactive python.jl®process_status¥ready¤pathÙH/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl­pluto_version¨v0.19.47®last_save_timeËAÚþbACªcell_orderÜ Ù$e07e4a47-a3cc-4ca4-a946-29e7df33ec6dÙ$73c3f448-be7d-49b7-9e39-18c3a08feb01Ù$f93f0eef-bb0c-45ee-a080-e8eeb6611176Ù$f4d3b313-1c8c-4de1-b5bd-592cb1112068Ù$dd20f208-0e39-4255-b35a-a8189986a165Ù$5dc1c311-1004-4056-b0a9-06622546486eÙ$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bÙ$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7Ù$12814f02-7e90-401a-9573-5c6b2f8067aeÙ$e8873c23-139d-41bc-be35-ebd636e48aeeÙ$005b40d9-bd89-4491-9807-d33a6c674b75Ù$b59d932b-6425-47c2-a67d-208113bc8b7bÙ$6449e96f-19ce-4100-8b35-56113bc24b7dÙ$d9bc5dc1-67b6-47c6-9592-3b474ec451a0Ù$71ca495d-39ad-4d52-94a5-d4248679ce1eÙ$ab92a31d-1ef4-427f-b1c7-fa2790278a14Ù$21199966-adc3-498e-87ae-62333810efb5Ù$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bÙ$56fcc0c2-0ce0-445b-b602-6525bab173b3Ù$a1ada27d-8a1a-453a-ace7-ae07b68ad42aÙ$fb3fb09d-1ba7-431e-aba2-f832d259075aÙ$216e88b3-82cb-4d74-aae4-c21791980ac2Ù$56a3a022-6ed3-47d8-8d62-ce4ead5ca026Ù$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7eÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16Ù$5f5ab869-c551-42d3-9325-86ecdc424c9bÙ$d3fe9870-ac9d-4871-b8cc-1361a446b0a5Ù$688c93e7-b50f-4bb7-ab23-5686fd8ffb18Ù$b9903477-5070-43eb-82a9-8b750f79c8faÙ$600344b6-ff43-431b-b858-2bf30e93d938Ù$d74aed51-9542-47aa-8c3d-fb634c1a0212±published_objects€¥nbpkgŠ¯install_time_nsÏ   C=çg¬instantiatedÃ²installed_versionsƒ£Pkg¦stdlib§PlutoUI¦0.7.16¦PyCall¦1.92.3°terminal_outputs„£PkgÚø
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1mâ”” [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.92.3
            Installed           HypertextLiteral â”€ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing â”€â”€â”€ v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v2.0.6
[32m[1m   Installed[22m[39m PlutoUI â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v0.7.16
             Building           Conda â”€â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1mâ”‚ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1mâ”” [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)ªnbpkg_syncÚø
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1mâ”” [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.92.3
            Installed           HypertextLiteral â”€ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing â”€â”€â”€ v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v2.0.6
[32m[1m   Installed[22m[39m PlutoUI â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v0.7.16
             Building           Conda â”€â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1mâ”‚ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1mâ”” [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)§PlutoUIÚø
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1mâ”” [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.92.3
            Installed           HypertextLiteral â”€ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing â”€â”€â”€ v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v2.0.6
[32m[1m   Installed[22m[39m PlutoUI â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v0.7.16
             Building           Conda â”€â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1mâ”‚ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1mâ”” [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)¦PyCallÚø
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1mâ”” [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.92.3
            Installed           HypertextLiteral â”€ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing â”€â”€â”€ v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v2.0.6
[32m[1m   Installed[22m[39m PlutoUI â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ v0.7.16
             Building           Conda â”€â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall â†’ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1mâ”Œ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1mâ”‚ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1mâ”” [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)§enabledÃ·restart_recommended_msgÀ´restart_required_msgÀ­busy_packages�¶waiting_for_permissionÂÙ,waiting_for_permission_but_probably_disabledÂ«cell_inputsÞ Ù$005b40d9-bd89-4491-9807-d33a6c674b75„§cell_idÙ$005b40d9-bd89-4491-9807-d33a6c674b75¤codeÙ-begin
	py"""
	import math
	math.sin"""(2)
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$12814f02-7e90-401a-9573-5c6b2f8067ae„§cell_idÙ$12814f02-7e90-401a-9573-5c6b2f8067ae¤codeµ# Pkg.build("PyCall")¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$6449e96f-19ce-4100-8b35-56113bc24b7d„§cell_idÙ$6449e96f-19ce-4100-8b35-56113bc24b7d¤code²Dump(:(py"[1+1]"))¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$5f5ab869-c551-42d3-9325-86ecdc424c9b„§cell_idÙ$5f5ab869-c551-42d3-9325-86ecdc424c9b¤codeÙÿmacro pyr_old_str(str)
	var"@custom_py_str"
	
	reads, writes = py_reads_writes(str)

	quote
		if false
		$([esc(:($(Symbol("#py", s)) = 1))  for s in writes]...)
		$([esc(:($(Symbol("#py", s))))  for s in reads]...)
		end
		@custom_py_str($(str))
	end
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$56a3a022-6ed3-47d8-8d62-ce4ead5ca026„§cell_idÙ$56a3a022-6ed3-47d8-8d62-ce4ead5ca026¤codeÙbBase.remove_linenums!(Meta.macroexpand(@__MODULE__, :(pyr"""
x = 123
y = b
"""); recursive=false))¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$e07e4a47-a3cc-4ca4-a946-29e7df33ec6d„§cell_idÙ$e07e4a47-a3cc-4ca4-a946-29e7df33ec6d¤codeÚmd"""
# Reactive Python

The `pyr"` macro is just like the `py"` macro from `PyCall.jl`, except it is reactive! This means:
- If you define a Python variable, then other cells that use that python variable are also evaluated.
- The scope of Python variables is cleaned up automatically.
- Multiple definitions are not allowed.

This is using the Python port of Pluto.ExpressionExplorer by MikoÅ‚aj Bochenski: [https://github.com/lightning-notebook/engine](https://github.com/lightning-notebook/engine) and some Julia macro magic.
"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÃÙ$56fcc0c2-0ce0-445b-b602-6525bab173b3„§cell_idÙ$56fcc0c2-0ce0-445b-b602-6525bab173b3¤codeÙ2begin
	rand(), try
		var"#py_var_x"
	catch end
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$21199966-adc3-498e-87ae-62333810efb5„§cell_idÙ$21199966-adc3-498e-87ae-62333810efb5¤codeÙ%@macroexpand pyr"""
x = 123
y = b
"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$73c3f448-be7d-49b7-9e39-18c3a08feb01„§cell_idÙ$73c3f448-be7d-49b7-9e39-18c3a08feb01¤code´pyr"""
y = x + x
"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$fb3fb09d-1ba7-431e-aba2-f832d259075a„§cell_idÙ$fb3fb09d-1ba7-431e-aba2-f832d259075a¤code©pyr"f(1)"¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7„§cell_idÙ$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7¤codeªimport Pkg¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$600344b6-ff43-431b-b858-2bf30e93d938„§cell_idÙ$600344b6-ff43-431b-b858-2bf30e93d938¤codeÙÑmd"""
Following code is from [https://github.com/lightning-notebook/engine/blob/master/tests/test_variable_access.py](https://github.com/lightning-notebook/engine/blob/master/tests/test_variable_access.py)
"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÃÙ$688c93e7-b50f-4bb7-ab23-5686fd8ffb18„§cell_idÙ$688c93e7-b50f-4bb7-ab23-5686fd8ffb18¤codeµcustom_py"""
1 + 1"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$a1ada27d-8a1a-453a-ace7-ae07b68ad42a„§cell_idÙ$a1ada27d-8a1a-453a-ace7-ae07b68ad42a¤code£123¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$b9903477-5070-43eb-82a9-8b750f79c8fa„§cell_idÙ$b9903477-5070-43eb-82a9-8b750f79c8fa¤codeÚmacro custom_py_str(code, options...)
    T = length(options) == 1 && 'o' in options[1] ? PyObject : PyAny
    code, locals = interpolate_pycode(code)
    input_type = '\n' in code ? Py_file_input : Py_eval_input
    fname = make_fname(@__FILE__)
    assignlocals = Expr(:block, [(isa(v,String) ?
                                  :(m[$v] = PyObject($(esc(ex)))) :
                                  nothing) for (v,ex) in locals]...)
    code_expr = Expr(:call, esc(:(Base.string)))
    i0 = firstindex(code)
    for i in sort!(collect(filter(k -> isa(k,Integer), keys(locals))))
        push!(code_expr.args, code[i0:prevind(code,i)], esc(locals[i]))
        i0 = i
    end
    push!(code_expr.args, code[i0:lastindex(code)])
    if input_type == Py_eval_input
        removelocals = Expr(:block, [:(delete!(m, $v)) for v in keys(locals)]...)
    else
        # if we are evaluating multi-line input, then it is not
        # safe to remove the local variables, because they might be referred
        # to in Python function definitions etc. that will be called later.
        removelocals = nothing
    end
    quote
        m = pynamespace(Main)
        $assignlocals
        ret = $T(pyeval_($code_expr, m, m, $input_type, $fname))
        $removelocals
        ret
    end
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$71ca495d-39ad-4d52-94a5-d4248679ce1e„§cell_idÙ$71ca495d-39ad-4d52-94a5-d4248679ce1e¤code»rw = py_reads_writes("x=2")¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16„§cell_idÙ$5c432b4e-60e0-4288-8d5a-42e364ce8d16¤codeÚÇmacro pyr_str(str)
	var"@custom_py_str"
	
	reads, writes = py_reads_writes(str)

	quote
		# if false
		$([let
			julia_s = Symbol("py#var_", py_s)
			import_code = """$(py_s) = \$(s)\n"""
			esc(quote
				let s = $(julia_s) # for pluto to recognise
				@custom_py_str($(import_code)) # load stored PyObject into python using that name
				end
			end)
		end for py_s in reads]...)
		# end
		
		output = @custom_py_str($(str))
		
		# if false

		$([let
			julia_s = Symbol("py#var_", py_s)
			import_code = "$(py_s)"
			esc(quote
				$(julia_s) = @custom_py_str($(import_code)) # store PyObject as julia object, so that it can use Pluto's reactivity
			end)
		end for py_s in writes]...)
		# end
		output
	end
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$f4d3b313-1c8c-4de1-b5bd-592cb1112068„§cell_idÙ$f4d3b313-1c8c-4de1-b5bd-592cb1112068¤code«pyr"[x, y]"¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$5dc1c311-1004-4056-b0a9-06622546486e„§cell_idÙ$5dc1c311-1004-4056-b0a9-06622546486e¤code¯pyr"cool(x, x)"¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7e„§cell_idÙ$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7e¤codeÙ%# string(Expr(:symbol, Symbol("#a")))¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b„§cell_idÙ$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b¤code¬using PyCall¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$d9bc5dc1-67b6-47c6-9592-3b474ec451a0„§cell_idÙ$d9bc5dc1-67b6-47c6-9592-3b474ec451a0¤code¸Dump(:(py"""
[1+1]
"""))¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$e8873c23-139d-41bc-be35-ebd636e48aee„§cell_idÙ$e8873c23-139d-41bc-be35-ebd636e48aee¤codeÙ=begin
	py"""
	import math
	math.sin
	"""
	py"math.sin"(2)
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$d74aed51-9542-47aa-8c3d-fb634c1a0212„§cell_idÙ$d74aed51-9542-47aa-8c3d-fb634c1a0212¤codeÚ¬py_reads_writes = begin
	py"""
	import ast
	import functools
	
	
	
	class VariableAccess:
	    def __init__(self, reads, writes):
	        self.reads = frozenset(reads)
	        self.writes = frozenset(writes)
	    
	
	    @classmethod
	    def from_code(cls, code):
	        return cls.from_ast(ast.parse(code))
	    
	
	    @classmethod
	    def from_ast(cls, ast_node):
	        if isinstance(ast_node, ast.Name):
	            return cls(reads=[ast_node.id], writes=[])
	
	        if isinstance(ast_node, ast.Assign):
	            targets = cls.from_ast(ast_node.targets)
	            value = cls.from_ast(ast_node.value)
	            return cls(reads=value.reads, writes=targets.reads | targets.writes | value.writes)
	        if isinstance(ast_node, ast.AugAssign): # x += 3, for example
	            target = cls.from_ast(ast_node.target)
	            value = cls.from_ast(ast_node.value)
	            return cls(reads=value.reads, writes=target.reads | target.writes | value.writes)
	        
	        if isinstance(ast_node, ast.ImportFrom):
	            if ast_node.names[0].name == '*':
	                raise NotImplementedError('"import *" is not supported yet!')
	            return cls.from_ast(ast_node.names)
	        if isinstance(ast_node, ast.alias):
	            return cls(reads=[], writes=[ast_node.asname or ast_node.name])
	        
	        if isinstance(ast_node, ast.ClassDef):
	            bases = cls.from_ast(ast_node.bases)
	            keywords = cls.from_ast(ast_node.keywords)
	            decorators = cls.from_ast(ast_node.decorator_list)
	            body = cls.from_ast(ast_node.body) # no name shadowing because of "if x: y = 10"
	            return cls(
	                reads=bases.reads | keywords.reads | decorators.reads | body.reads,
	                writes=[ast_node.name]
	            )
	        
	        if isinstance(ast_node, ast.Lambda):
	            arguments = cls.from_ast(ast_node.args)
	            body = cls.from_ast(ast_node.body)
	            return cls(reads=arguments.reads | (body.reads - arguments.writes), writes=[])
	        if isinstance(ast_node, ast.FunctionDef):
	            decorators = cls.from_ast(ast_node.decorator_list)
	            arguments = cls.from_ast(ast_node.args)
	            body = cls.from_ast(ast_node.body)
	            return cls(reads=decorators.reads | arguments.reads | (body.reads - arguments.writes), writes=[ast_node.name])
	        if isinstance(ast_node, ast.arg):
	            return cls(reads=[], writes=[ast_node.arg])
	
	        if isinstance(ast_node, ast.For):
	            target = cls.from_ast(ast_node.target) # no name shadowing - target is actually written to
	            iterable = cls.from_ast(ast_node.iter)
	            body = cls.from_ast(ast_node.body)
	            else_body = cls.from_ast(ast_node.orelse)
	            return cls(
	                reads=iterable.reads | body.reads | else_body.reads,
	                writes=target.reads | target.writes | iterable.writes | body.writes | else_body.writes
	            )
	        
	        if isinstance(ast_node, ast.ListComp):
	            element = cls.from_ast(ast_node.elt)
	            generators = cls.from_ast(ast_node.generators)
	            return element | generators # TODO: name shadowing
	        if isinstance(ast_node, ast.SetComp):
	            element = cls.from_ast(ast_node.elt)
	            generators = cls.from_ast(ast_node.generators)
	            return element | generators # TODO: name shadowing
	        if isinstance(ast_node, ast.DictComp):
	            key = cls.from_ast(ast_node.key)
	            value = cls.from_ast(ast_node.value)
	            generators = cls.from_ast(ast_node.generators)
	            return key | value | generators # TODO: name shadowing
	        if isinstance(ast_node, ast.comprehension):
	            target = cls.from_ast(ast_node.target)
	            iterable = cls.from_ast(ast_node.iter)
	            conditions = cls.from_ast(ast_node.ifs)
	            return target | iterable | conditions # TODO: name shadowing
	        
	        if isinstance(ast_node, list):
	            return functools.reduce(
	                cls.__or__,
	                [cls.from_ast(sub_ast) for sub_ast in ast_node],
	                cls(reads=[], writes=[])
	            )
	        
	        for node_type, children in node_children.items():
	            if isinstance(ast_node, node_type):
	                return cls.from_ast([getattr(ast_node, child) for child in children])
	        
	        raise NotImplementedError(f'Cannot parse {type(ast_node)} yet!')
	
	
	    def __eq__(self, other):
	        return self.reads == other.reads and self.writes == other.writes
	
	
	    def __or__(self, other):
	        return type(self)(reads=self.reads | other.reads, writes=self.writes | other.writes)
	    
	
	    def __repr__(self):
	        return f'{type(self).__name__}(reads={list(self.reads)}, writes={list(self.writes)})'
	
	
	node_children = {
	    ast.Constant: [],
	    ast.Pass: [],
	    type(None): [],
	    ast.Expression: ['body'],
	    ast.Expr: ['value'],
	    ast.Module: ['body'],
	    ast.Import: ['names'],
	    ast.Attribute: ['value'],
	    ast.arguments: ['posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kwarg', 'defaults', 'kw_defaults'],
	    ast.Return: ['value'],
	    ast.Call: ['func', 'args', 'keywords'],
	    ast.keyword: ['value'],
	    ast.If: ['test', 'body', 'orelse'],
	    ast.IfExp: ['test', 'body', 'orelse'],
	    ast.While: ['test', 'body', 'orelse'],
	    ast.Tuple: ['elts'],
	    ast.List: ['elts'],
	    ast.Set: ['elts'],
	    ast.Dict: ['keys', 'values'],
	    ast.JoinedStr: ['values'],
	    ast.FormattedValue: ['value'],
	    ast.Subscript: ['value', 'slice'],
	    ast.Index: ['value'],
	    ast.Slice: ['lower', 'upper', 'step'],
	    ast.UnaryOp: ['operand'],
	    ast.BinOp: ['left', 'right'],
	    ast.BoolOp: ['values'],
	    ast.Compare: ['left', 'comparators']
	}

	def reads_writes(code):
		va = VariableAccess.from_code(code)
		return [va.reads, va.writes]
	"""
	
	py"reads_writes"
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÃÙ$ab92a31d-1ef4-427f-b1c7-fa2790278a14„§cell_idÙ$ab92a31d-1ef4-427f-b1c7-fa2790278a14¤code°rw[2] |> collect¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$b59d932b-6425-47c2-a67d-208113bc8b7b„§cell_idÙ$b59d932b-6425-47c2-a67d-208113bc8b7b¤code­using PlutoUI¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b„§cell_idÙ$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b¤codeÙ2begin
	custom_py"""
	x = 3
	"""

	custom_py"x"
end¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$d3fe9870-ac9d-4871-b8cc-1361a446b0a5„§cell_idÙ$d3fe9870-ac9d-4871-b8cc-1361a446b0a5¤codeÙaimport PyCall: interpolate_pycode, Py_file_input, make_fname, Py_eval_input, pynamespace, pyeval_¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$dd20f208-0e39-4255-b35a-a8189986a165„§cell_idÙ$dd20f208-0e39-4255-b35a-a8189986a165¤codeÙ)pyr"""
def cool(x, y):
	return 123123
"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$f93f0eef-bb0c-45ee-a080-e8eeb6611176„§cell_idÙ$f93f0eef-bb0c-45ee-a080-e8eeb6611176¤code°pyr"""
x = 2
"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂÙ$216e88b3-82cb-4d74-aae4-c21791980ac2„§cell_idÙ$216e88b3-82cb-4d74-aae4-c21791980ac2¤codeÙ(pyr"""
def f(x):
	return x + 1123123
"""¨metadataƒ©show_logsÃ¨disabledÂ®skip_as_scriptÂ«code_foldedÂ«notebook_idÙ$410e9fe0-4aa1-11f0-23e4-ebbda5fc8a98«in_temp_dirÂ¨metadata€